#include <video_process.h>
#include <libyuv.h>

using namespace libyuv;

//#define WRITE_RGB24_FILE
/*
for m in range(height-10):
     for n in range(width-10):
         if m%10 == 0 and n%10==0:
             for i in range(10):
                 for j in range(10):
                     b,g,r=img[m,n]
                     img[m+i,n+j]=(b,g,r)
*/



 video_process::video_process()
 {
    m_rgb_buffer = (unsigned char*)malloc(m_target_width* m_target_height* 3);
    m_nv12_buffer = (unsigned char*)malloc(m_target_width* m_target_height* 3 /2);
 }
video_process::~video_process()
{
    if(m_rgb_buffer) {
        delete m_rgb_buffer;
    }
    if(m_nv12_buffer) {
        delete m_nv12_buffer;
    }
}   

std::vector<rectangle> video_process::preprocess(AVFrame* frame)
{
    std::vector<rectangle> rects;
    rectangle rect ;
    rect.left_top.x = 400;
    rect.left_top.y = 400;
    rect.right_bottom.x = 800;
    rect.right_bottom.y = 800;
    rects.push_back(rect) ; 

    libyuvNV12Scale(frame->data[0],frame->data[1],frame->width,frame->height,m_nv12_buffer,m_target_width,m_target_height);   

    #ifdef WRITE_RGB24_FILE
        static int write_nv12_once = 0;
        if(write_nv12_once== 0) {
            write_nv12_once = 1;
            FILE* p_file = fopen("test.nv12","wb");
            fwrite(m_nv12_buffer,1,m_target_width*m_target_height*3/2,p_file);            
            fclose(p_file);
        }
    #endif


    libyuvNV12ToRGB24(m_nv12_buffer,m_rgb_buffer,m_target_width,m_target_height);

    #ifdef WRITE_RGB24_FILE
        static int write_once = 0;
        if(write_once== 0) {
            write_once = 1;
            FILE* p_file = fopen("test.rgb","wb");
            fwrite(m_rgb_buffer,1,m_target_width*m_target_height*3,p_file);
            fclose(p_file);
        }
    #endif

    return rects;
}

void video_process::libyuvNV12Scale(unsigned char *src_y,unsigned char* src_uv,
    int width,
    int height,
    unsigned char* dst,
    int out_width,
    int out_height) {
        
        unsigned char *p_src_UV = src_uv;
        unsigned char *p_dst_Y = dst;
        unsigned char *p_dst_UV = dst+ out_width*out_height;

    NV12Scale(src_y, width, src_uv, width,width,height, p_dst_Y, out_width , p_dst_UV,out_width,out_width, out_height,libyuv::kFilterNone);
}

void video_process::libyuvNV12ToRGB24(unsigned char *src, unsigned char *dst, int width, int height) {
    unsigned char *pY = src;
    unsigned char *pUV = src + width * height;
    NV12ToRGB24(pY, width, pUV, width, dst, width*3 , width, height);
}


int video_process::process(AVFrame* frame)
{
    const int step = 32;
    if(frame->format == AV_PIX_FMT_NV12)
    {

        

        std::vector<rectangle> positions= preprocess(frame);
        std::vector<rectangle>::iterator it = positions.begin();

        

        for(; it != positions.end(); it++)
        {
            for(int m=it->left_top.y/step*step;m < it->right_bottom.y; m+=step)
                for(int n=it->left_top.x/step*step; n<it->right_bottom.x; n+=step)
                {
                    if(m%step == 0 && n%step== 0)
                    {
                        for(int i=0; i <step;i++ )
                            for(int j=0; j<step; j++)
                            {
                            //y img[m,n] m+n*width
                                *(frame->data[0] + (n+i+(m+j)*frame->width)) = *(frame->data[0] + (n+(m*frame->width)));                           
                            //u
                            //*(frame->data[1] + ((n+i)+(m+j)*frame->width/2)) = *(frame->data[1] + (n+(m*frame->width)/2));    
                            //v
                            //*(frame->data[1] + ((n+i)+(m+j)*frame->width/2) + 1) = *(frame->data[1] + (n+(m*frame->width)/2)+1);                       
                            }
                    }
                }
        }

    }else {
        printf("not support format %d\n",frame->format);
    }
 return 0;
}